#ifndef __BASIC_OSSL_H__
#define	__BASIC_OSSL_H__

#include <basic/misc.h>

__BEGIN_DECLS

#define OSSL_PLAIN_MAX_SIZE         KB(256)

struct _ossl_key;
typedef struct _ossl_key *OSSL_KEY;

/*
 * 初始化加密环境（单线程）
 */
extern void
ossl_init();

/*
 * 初始化加密环境（多线程）
 */
extern void
ossl_init_mt();

/*
 * 清除加密环境（单线程）
 */
extern void
ossl_clean();
 
/*
 * 清除加密环境（多线程）
 */
extern void
ossl_clean_mt();

enum
{
    OSSL_DIGEST_MD5 = 1,
    OSSL_DIGEST_SHA1,
    /* openssl >= 0.9.8 */
    OSSL_DIGEST_SHA224,
    OSSL_DIGEST_SHA256,
    OSSL_DIGEST_SHA384,
    OSSL_DIGEST_SHA512
};

/*
 * 为缓冲区中数据生成校验值
 */
extern int  /* 0:成功 -1:不支持的算法
               -2,-3,-4:openssl调用错误 */
ossl_digest(
        unsigned int algm,      /* [IN] enum中列出的算法 */
        unsigned char *data,    /* [IN] 数据缓冲区 */
        int data_size,          /* [IN] 数据长度 */
        unsigned char *value,   /* [OUT] 校验值缓冲区，>=16字节 */
        int *value_size         /* [OUT] 校验值长度 */
        );

extern int
base64_wrap(
        char *inp,
        char *outp
        );

extern int
base64_unwrap(
        char *inp,
        char *outp
        );

/*
 * 为文件中数据生成校验值
 */
extern int  /* 0:成功 -1:不支持的算法
               -2,-3,-4,-5:openssl调用错误 */
ossl_digest_file(
        unsigned int algm,      /* [IN] enum中列出的算法 */
        char *filename,         /* [IN] 文件名 */
        unsigned char *value,   /* [OUT] 校验值缓冲区，>=16字节 */
        int *value_size         /* [OUT] 校验值长度 */
        );

enum
{
    OSSL_ENCODE_BASE64 = 1
};

/*
 * 编码数据
 */
extern int  /* 0:成功 -1:不支持的算法
               -2,-3,-4,-5:openssl调用错误 */
ossl_encode(
        unsigned int algm,      /* [IN] 算法 */
        unsigned char *plain,   /* [IN] 原数据 */
        int plain_size,         /* [IN] 原数据长度 */
        char *enc,              /* [OUT] 编码数据 */
        int *p_enc_size         /* [OUT] 编码数据长度 */
        );

/*
 * 编码文件
 */
extern int  /* 0:成功 -1:不支持的算法
               -2,-3,-4,-5:openssl调用错误 */
ossl_encode_file(
        unsigned int algm,      /* [IN] 算法 */
        char *plain_file,       /* [IN] 原文件 */
        char *enc,              /* [OUT] 编码数据 */
        int *p_enc_size         /* [OUT] 编码数据长度 */
        );

/*
 * 编码文件输出到文件
 */
extern int  /* 0:成功 -1:不支持的算法
               -2,-3,-4:openssl调用错误 */
ossl_encode_file_to_file(
        unsigned int algm,      /* [IN] 算法 */
        char *plain_file,       /* [IN] 原文件 */
        char *enc_file          /* [IN] 编码文件 */
        );

/*
 * 还原编码数据
 */
extern int  /* 0:成功 -1:不支持的算法
               -2,-3:openssl调用错误 */
ossl_decode(
        unsigned int algm,      /* [IN] 算法 */
        char *enc,              /* [IN] 编码数据 */
        int enc_size,           /* [IN] 编码数据长度 */
        unsigned char *plain,   /* [OUT] 原数据 */
        int *p_plain_size       /* [OUT] 原数据长度 */
        );

/*
 * 还原编码文件
 */
extern int  /* 0:成功 -1:不支持的算法
               -2,-3:openssl调用错误 */
ossl_decode_file(
        unsigned int algm,      /* [IN] 算法 */
        char *enc_file,         /* [IN] 编码文件 */
        unsigned char *plain,   /* [OUT] 原数据 */
        int *p_plain_size       /* [OUT] 原数据长度 */
        );

/*
 * 还原编码文件输出到文件
 */
extern int  /* 0:成功 -1:不支持的算法
               -2,-3,-4:openssl调用错误 */
ossl_decode_file_to_file(
        unsigned int algm,      /* [IN] 算法 */
        char *enc_file,         /* [IN] 编码文件 */
        char *plain_file        /* [IN] 原文件 */
        );

extern int
random_padding(
        unsigned char *src,
        int src_size,
        unsigned char *dest,
        int *dest_size
        );

extern int
random_unpadding(
        unsigned char *src,
        int src_size,
        unsigned char *dest,
        int *dest_size
        );

enum
{
    OSSL_SYM_DES_CBC = 1,
    OSSL_SYM_DES_ECB,
    OSSL_SYM_DES_EDE_CBC,
    OSSL_SYM_DES_EDE_ECB,
    OSSL_SYM_DES_EDE3_CBC,
    OSSL_SYM_DES_EDE3_ECB,
    OSSL_SYM_AES_128_CBC,
    OSSL_SYM_AES_128_ECB,
    OSSL_SYM_AES_192_CBC,
    OSSL_SYM_AES_192_ECB,
    OSSL_SYM_AES_256_CBC,
    OSSL_SYM_AES_256_ECB
};

enum
{
    OSSL_SYM_KEY,       /* 纯密钥 */
    OSSL_SYM_PASSWD     /* 口令 */
};

/*
 * 载入对称加密密钥
 */
extern int  /* 0:成功 -1:不支持的算法
               -2:密钥形式错误 */
ossl_sym_load_key(
        unsigned int algm,      /* [IN] 算法 */
        unsigned int form,      /* [IN] 密钥形式 OSSL_SYM_PASSWD OSSL_SYM_KEY */
        char *text,             /* [IN] 文本 */
        OSSL_KEY *p_key         /* [OUT] 密钥句柄 */
        );

/*
 * 释放对称加密密钥
 */
extern void
ossl_sym_free_key(
        OSSL_KEY key            /* [IN] 密钥句柄 */
        );

/*
 * 显示对称加密密钥
 */
extern int
ossl_sym_get_key(
        OSSL_KEY key,           /* [IN] 密钥句柄 */
        char *key_txt,          /* [OUT] 密钥文本  */
        char *iv_txt            /* [OUT] 初始变量文本 */
        );

/*
 * 对称加密
 */
extern int  /* 0:成功 -1,-2,-3:openssl调用错误 */
ossl_sym_encrypt(
        OSSL_KEY key,           /* [IN] 密钥句柄 */
        unsigned char *plain,   /* [IN] 明文 */
        int plain_size,         /* [IN] 明文长度 */
        unsigned char *enc,     /* [OUT] 密文 */
        int *p_enc_size         /* [OUT] 密文长度 */
        );

/*
 * 对称解密
 */
extern int  /* 0:成功 -1,-2,-3:openssl调用错误 */
ossl_sym_decrypt(
        OSSL_KEY key,           /* [IN] 密钥句柄 */
        unsigned char *enc,     /* [IN] 密文 */
        int enc_size,           /* [IN] 密文长度 */
        unsigned char *plain,   /* [OUT] 明文 */
        int *p_plain_size       /* [OUT] 明文长度 */
        );

/*
 * 生成RSA密钥对
 */
extern int  /* 0:成功 -1,-2,-3,-4,-5,-6,-7:openssl调用错误 */
ossl_rsa_generate_key_pair(
        unsigned int key_bits,      /* [IN] 密钥长度 */
        char *private_key_passwd,   /* [IN] 私钥口令 */
        char *public_key_pem,       /* [OUT] 公钥 */
        char *private_key_pem       /* [OUT] 私钥 */
        );

/*
 * 生成RSA密钥对文件
 */
extern int  /* 0:成功 -1,-2,-3,-4,-5:openssl调用错误 */
ossl_rsa_generate_key_pair_file(
        unsigned int key_bits,      /* [IN] 密钥长度 */
        char *private_key_passwd,   /* [IN] 私钥口令 */
        char *public_key_pem_file,  /* [IN] 公钥文件 */
        char *private_key_pem_file  /* [IN] 私钥文件 */
        );

/*
 * 载入公钥
 */
extern int  /* 0:成功 -1,-2:openssl调用错误 */
ossl_rsa_load_public_key(
        char *key_pem,          /* [IN] 密钥文本 */
        OSSL_KEY *pkey          /* [OUT] 密钥句柄 */
        );

/*
 * 载入公钥文件
 */
extern int  /* 0:成功 -1,-2,-3:openssl调用错误 */
ossl_rsa_load_public_key_file(
        char *key_pem_file,     /* [IN] 密钥文件 */
        OSSL_KEY *pkey          /* [OUT] 密钥句柄 */
        );

/*
 * 载入私钥
 */
extern int  /* 0:成功 -1,-2:openssl调用错误 */
ossl_rsa_load_private_key(
        char *key_pem,          /* [IN] 密钥文本 */
        char *passwd,           /* [IN] 密钥口令 */
        OSSL_KEY *pkey          /* [OUT] 密钥句柄 */
        );

/*
 * 载入私钥文件
 */
extern int  /* 0:成功 -1,-2,-3:openssl调用错误 */
ossl_rsa_load_private_key_file(
        char *key_pem_file,     /* [IN] 密钥文件 */
        char *passwd,           /* [IN] 密钥口令 */
        OSSL_KEY *pkey          /* [OUT] 密钥句柄 */
        );

/*
 * 释放RSA密钥
 */
extern void
ossl_rsa_free_key(
        OSSL_KEY key            /* [IN] 密钥句柄 */
        );

/*
 * RSA加密
 */
extern int  /* 0:成功 -1:openssl调用错误 */
ossl_rsa_encrypt(
        OSSL_KEY public_key,    /* [IN] 公钥句柄 */
        unsigned char *plain,   /* [IN] 明文 */
        int plain_size,         /* [IN] 明文长度 */
        unsigned char *enc,     /* [OUT] 密文 */
        int *p_enc_size         /* [OUT] 密文长度 */
        );


/*
 * RSA解密
 */
extern int  /* 0:成功 -1:openssl调用错误 */
ossl_rsa_decrypt(
        OSSL_KEY private_key,   /* [IN] 私钥句柄 */
        unsigned char *enc,     /* [IN] 密文 */
        int enc_size,           /* [IN] 密文长度 */
        unsigned char *plain,   /* [OUT] 明文 */
        int *p_plain_size       /* [OUT] 明文长度 */
        );

/*
 * RSA签名
 */
extern int  /* 0:成功 -1:openssl调用错误 */
ossl_rsa_sign(
        OSSL_KEY private_key,   /* [IN] 私钥句柄 */
        unsigned char *data,    /* [IN] 数据 */
        int data_size,          /* [IN] 数据明文长度 */
        unsigned char *sign,    /* [OUT] 签名 */
        int *p_sign_size        /* [OUT] 签名长度 */
        );

/*
 * RSA校验
 */
extern int  /* 0:成功 -1:openssl调用错误 */
ossl_rsa_verify(
        OSSL_KEY public_key,    /* [IN] 公钥句柄 */
        unsigned char *data,    /* [IN] 数据 */
        int data_size,          /* [IN] 数据长度 */
        unsigned char *sign,    /* [IN] 签名 */
        int sign_size           /* [IN] 签名长度 */
        );

__END_DECLS

#endif
